package com.wh.wisdomsite.xbox.core.config.spring;

import com.wh.wisdomsite.xbox.core.ServiceDispatcher;
import com.wh.wisdomsite.xbox.core.event.XboxEventListener;
import com.wh.wisdomsite.xbox.core.impl.ServiceDispatcherImpl;
import com.wh.wisdomsite.xbox.core.interceptor.Interceptor;
import com.wh.wisdomsite.xbox.core.security.AppSecretManager;
import com.wh.wisdomsite.xbox.core.security.impl.XboxSecurityManager;
import com.wh.wisdomsite.xbox.core.security.InvokeTimesController;
import com.wh.wisdomsite.xbox.core.security.ServiceAccessController;
import com.wh.wisdomsite.xbox.common.session.SessionManager;
import com.wh.wisdomsite.xbox.core.threadpool.JobDispathcher;
import com.wh.wisdomsite.xbox.core.util.GlobalThreadPool;
import com.wh.wisdomsite.xbox.core.security.SecurityManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.util.*;

/**
 *
 * @Package com.wh.wisdomsite.xbox.core.config.spring
 * @author 谢泽鹏
 * @date 2014年10月8日 下午4:02:14
 * @Copyright 个人版权所有
 * @Company 贵州万华科技有限公司Copyright (c) 2014
 * @version V1.0
 */
public class ServiceDispatherFactoryBean implements InitializingBean, DisposableBean, FactoryBean<ServiceDispatcher>, ApplicationContextAware {

    private static final Log logger = LogFactory.getLog(ServiceDispatherFactoryBean.class);

    /**
     * 上下文
     */
    private ApplicationContext applicationContext;

    /**
     * 服务分发类
     */
    private ServiceDispatcher serviceDispatcher;

    /**
     * 会话管理器
     */
    private SessionManager sessionManager;

    /**
     * app管理器
     */
    private AppSecretManager appSecretManager;

    /**
     * 服务访问控制器
     */
    private ServiceAccessController serviceAccessController;

    /**
     * 访问频率/次数控制器
     */
    private InvokeTimesController invokeTimesController;

    /**
     * 权重线程池
     */
    private JobDispathcher jobDispathcher;

    /**
     * 扩展的错误配置信息
     */
    private String extErrorBaseName;

    /**
     * 是否开启签名
     */
    private boolean signEnable;

    /**
     * 事件是否实用异步模式
     */
    private boolean eventAsync;

    @Override
    public void afterPropertiesSet() throws Exception {
        serviceDispatcher = new ServiceDispatcherImpl();

        //设置属性
        if (extErrorBaseName != null) {
            serviceDispatcher.setExtErrorBaseName(extErrorBaseName);
        }
        //设置安全管理器
        SecurityManager securityManager = BeanUtils.instantiate(XboxSecurityManager.class);
        securityManager.setAppSecretManager(appSecretManager);
        securityManager.setSessionManager(sessionManager);
        securityManager.setInvokeTimesController(invokeTimesController);
        securityManager.setServiceAccessController(serviceAccessController);

        //初始化
        serviceDispatcher.setSessionManager(sessionManager);
        serviceDispatcher.setSecurityManager(securityManager);
        serviceDispatcher.setSignEnable(this.signEnable);
        serviceDispatcher.setInvokeTimesController(invokeTimesController);
        serviceDispatcher.setJobDispathcher(jobDispathcher);
        serviceDispatcher.setEventAsync(eventAsync);


        //注册拦截器
        List<Interceptor> interceptors = getInterceptors();
        if (interceptors != null) {
            for (Interceptor interceptor : interceptors) {
                serviceDispatcher.addInterceptor(interceptor);
            }
            logger.info("共注册了" + interceptors.size() + "拦截器.");
        }

        //注册监听器
        List<XboxEventListener> listeners = getListeners();
        if (listeners != null) {
            for (XboxEventListener listener : listeners) {
                serviceDispatcher.addListener(listener);
            }
            logger.info("共注册了" + listeners.size() + "事件监听器.");
        }
        //设置spring上下文信息
        serviceDispatcher.setApplicationContext(this.applicationContext);
        //初始化权重线程池
        jobDispathcher.init();
        //启动框架
        serviceDispatcher.startup();
    }

    private List<Interceptor> getInterceptors() {
        Map<String, InterceptorHolder> interceptorMap = this.applicationContext.getBeansOfType(InterceptorHolder.class);
        if (interceptorMap != null && interceptorMap.size() > 0) {
            ArrayList<Interceptor> interceptors = new ArrayList<Interceptor>(interceptorMap.size());

            //从Spring容器中获取Interceptor
            for (InterceptorHolder interceptorHolder : interceptorMap.values()) {
                interceptors.add(interceptorHolder.getInterceptor());
            }

            //根据getOrder()值排序
            Collections.sort(interceptors, new Comparator<Interceptor>() {
                public int compare(Interceptor o1, Interceptor o2) {
                    if (o1.getOrder() > o2.getOrder()) {
                        return 1;
                    } else if (o1.getOrder() < o2.getOrder()) {
                        return -1;
                    } else {
                        return 0;
                    }
                }
            });
            return interceptors;
        } else {
            return null;
        }
    }

    private ArrayList<XboxEventListener> getListeners() {
        Map<String, XboxListenerHolder> listenerMap = this.applicationContext.getBeansOfType(XboxListenerHolder.class);
        if (listenerMap != null && listenerMap.size() > 0) {
            ArrayList<XboxEventListener> ropEventListeners = new ArrayList<XboxEventListener>(listenerMap.size());

            //从Spring容器中获取Interceptor
            for (XboxListenerHolder listenerHolder : listenerMap.values()) {
                ropEventListeners.add(listenerHolder.getXboxEventListener());
            }
            return ropEventListeners;
        } else {
            return null;
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public void destroy() throws Exception {
        serviceDispatcher.shutdown();
        GlobalThreadPool.shutdown();
        logger.info("Spring 容器关闭成功..");
    }

    @Override
    public ServiceDispatcher getObject() throws Exception {
        return this.serviceDispatcher;
    }

    @Override
    public Class<?> getObjectType() {
        return ServiceDispatcher.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    public ServiceDispatcher getServiceDispatcher() {
        return serviceDispatcher;
    }

    public void setServiceDispatcher(ServiceDispatcher serviceDispatcher) {
        this.serviceDispatcher = serviceDispatcher;
    }

    public SessionManager getSessionManager() {
        return sessionManager;
    }

    public void setSessionManager(SessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    public AppSecretManager getAppSecretManager() {
        return appSecretManager;
    }

    public void setAppSecretManager(AppSecretManager appSecretManager) {
        this.appSecretManager = appSecretManager;
    }

    public ServiceAccessController getServiceAccessController() {
        return serviceAccessController;
    }

    public void setServiceAccessController(ServiceAccessController serviceAccessController) {
        this.serviceAccessController = serviceAccessController;
    }

    public InvokeTimesController getInvokeTimesController() {
        return invokeTimesController;
    }

    public void setInvokeTimesController(InvokeTimesController invokeTimesController) {
        this.invokeTimesController = invokeTimesController;
    }

    public JobDispathcher getJobDispathcher() {
        return jobDispathcher;
    }

    public void setJobDispathcher(JobDispathcher jobDispathcher) {
        this.jobDispathcher = jobDispathcher;
    }

    public String getExtErrorBaseName() {
        return extErrorBaseName;
    }

    public void setExtErrorBaseName(String extErrorBaseName) {
        this.extErrorBaseName = extErrorBaseName;
    }

    public boolean isSignEnable() {
        return signEnable;
    }

    public void setSignEnable(boolean signEnable) {
        this.signEnable = signEnable;
    }

    public boolean isEventAsync() {
        return eventAsync;
    }

    public void setEventAsync(boolean eventAsync) {
        this.eventAsync = eventAsync;
    }


}
